<template>
    <div
        class="handle_bar vo-drag-position-item"
        :class="{
            'select': isSelect
        }"
        :style="itemStyle"
        @click.prevent.stop="handleItemClick()"
    >
        <vueDraggable
            class="vo-drag-position-item_draggable"
            v-model="item.children"
            :group="{
                name: 'drag-position'
            }"
            handle=".handle_bar"
        >
            <div class="handle_bar">
                <p>
                    <span>[{{item.width}}x{{item.height}}] - </span>
                    <span>[{{item.left}}x{{item.top}}]</span>
                </p>
                <template v-if="item.children">
                    <VoDragPositionItem
                        v-for="(child, index) in item.children"
                        v-bind="child.props"
                        :canvasWidth="item.width"
                        :canvasHeight="item.height"
                        :item="child"
                        :currentItem="currentItem"
                        :key="index"
                        :operatorZIndex="operatorZIndex - 1"
                        @on-item-click="handleItemClick"
                    ></VoDragPositionItem>
                </template>
            </div>
        </vueDraggable>
        <div class="vo-drag-position-item_dragbar" :style="dragbarStyle" @mousedown.prevent.stop="handleMouseDown($event)">
            <svg width="18px" fill="currentColor" viewBox="0 0 24 24">
                <path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"></path>
                <path d="M0 0h24v24H0z" fill="none"></path>
            </svg>
        </div>
        <span class="vo-drag-position-item_resize" :style="resizeStyle" @mousedown.prevent.stop="handleResizeMouseDown"></span>
    </div>
</template>

<script>
import VueDraggable from 'vuedraggable'
export default {
    name: 'VoDragPositionItem',
    components: {
        VueDraggable
    },
    props: {
        item: {
            type: Object,
            required: true
        },
        // 当前选中
        currentItem: Object,
        // 画布宽度
        canvasWidth: Number,
        // 画布高度
        canvasHeight: Number,
        // 是否限制大小改变的上限与下限
        overstep: Boolean,
        // 限制最小宽度
        minResizeWidth: Number,
        // 限制最小高度
        minResizeHeight: Number,
        // 限制最大宽度
        maxResizeWidth: Number,
        // 限制最大高度
        maxResizeHeight: Number,
        // 操作符层级
        operatorZIndex: {
            type: Number,
            default: 999
        }
    },
    computed: {
        isSelect() {
            return this.item === this.currentItem
        },
        itemStyle() {
            if (!this.item) return null;
            const { width = 0, height = 0, top = 0, left = 0, x = 0, y = 0, z = 0 } = this.item;
            return {
                width: `${width}px`,
                height: `${height}px`,
                top: `${top}px`,
                left: `${left}px`
            }
        },
        dragbarStyle() {
            return {
                zIndex: this.operatorZIndex - 1
            }
        },
        resizeStyle() {
            return {
                zIndex: this.operatorZIndex - 1
            }
        }
    },
    methods: {
        // item点击
        handleItemClick(item) {
            this.$emit('on-item-click', item || this.item)
        },
        // item移动
        handleMouseDown(e) {
            document.onmousemove = null;
            document.onmouseup = null;
            // 获取目标元素
            const odiv = this.$el;
            odiv.classList.add('active')
            // 算出鼠标相对元素的位置
            const disX = e.clientX - odiv.offsetLeft;
            const disY = e.clientY - odiv.offsetTop;
            const disW = odiv.offsetWidth;
            const disH = odiv.offsetHeight;
            // 鼠标按下并移动的事件
            document.onmousemove = (e) => {
                // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
                let left = e.clientX - disX;
                let top = e.clientY - disY;
                if (this.overstep && this.canvasWidth) {
                    left = Math.min(Math.max(left, 0), this.canvasWidth - disW)
                }
                if (this.overstep && this.canvasHeight) {
                    top = Math.min(Math.max(top, 0), this.canvasHeight - disH)
                }
                this.item.left = left;
                this.item.top = top;
            };
            document.onmouseup = (e) => {
                odiv.classList.remove('active')
                document.onmousemove = null;
                document.onmouseup = null;
            };
        },
        // item大小改变
        handleResizeMouseDown(e) {
            document.onmousemove = null;
            document.onmouseup = null;
            // 算出鼠标相对元素的位置
            const cX = e.clientX;
            const cY = e.clientY;
            const width = this.item.width;
            const height = this.item.height;
            // 鼠标按下并移动的事件
            document.onmousemove = (e) => {
                // 用鼠标的位置减去鼠标相对元素的位置，得到元素的位置
                const w = e.clientX - cX;
                const h = e.clientY - cY;
                let left = width + w;
                let top = height + h;
                if (this.minResizeWidth) {
                    left = Math.max(left, this.minResizeWidth)
                }
                if (this.minResizeHeight) {
                    top = Math.max(top, this.minResizeHeight)
                }
                if (this.maxResizeWidth) {
                    left = Math.min(left, this.maxResizeWidth)
                }
                if (this.maxResizeHeight) {
                    top = Math.min(top, this.maxResizeHeight)
                }
                this.item.width = left;
                this.item.height = top;
            };
            document.onmouseup = (e) => {
                document.onmousemove = null;
                document.onmouseup = null;
            };
        }
    }
}
</script>

<style lang="scss" scoped>
.vo-drag-position-item{
    position: absolute;
    left: 0;
    top: 0;
    display: inline-block;
    box-sizing: border-box;
    border: solid 1px transparent;
    border-radius: 4px;
    background: #fff;
    overflow: hidden;
    z-index: 1;
    transition: box-shadow 200ms cubic-bezier(0, 0, 0.2, 1);
    box-shadow: 0 3px 1px -2px rgba(0,0,0,20%), 0 2px 2px 0 rgba(0,0,0,14%), 0 1px 5px 0 rgba(0,0,0,12%);

    &.select{
        border-color: #ccc;
        z-index: 2;
        & > .vo-drag-position-item_dragbar{
            display: inline-block;
        }
        & > .vo-drag-position-item_resize{
            display: inline-block;
        }
    }
    &.active{
        z-index: 2;
        box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
            0 8px 10px 1px rgba(0, 0, 0, 0.14),
            0 3px 14px 2px rgba(0, 0, 0, 0.12);
    }
    .vo-drag-position-item_draggable{
        position: absolute;
        width: 100%;
        height: 100%;
        // overflow: hidden;
    }
    .vo-drag-position-item_dragbar{
        display: none;
        position: absolute;
        top: 0;
        right: 0;
        cursor: move;
    }
    .vo-drag-position-item_resize{
        position: absolute;
        bottom: 0;
        right: 0;
        display: none;
        width: 10px;
        height: 10px;
        background: #fff;
        border: solid 1px #ccc;
        background: #fff;
        cursor: nw-resize;
    }
}
</style>
